package com.herr.springboot.self.xxx.common.extend;

import com.herr.springboot.self.xxx.common.util.CommonUtils;
import com.herr.springboot.self.xxx.common.util.CustomCachingRequestWrapper;
import com.herr.springboot.self.xxx.common.util.LogUtils;
import com.herr.springboot.self.xxx.common.constant.APIConstant;
import com.herr.springboot.self.xxx.common.util.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 日志过滤器
 * @author herr05
 */
@Slf4j
public class LogFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        MDC.clear();
        // 给本次请求分配一个唯一的requestid
        String requestId = CommonUtils.generateGUID(32);
        MDC.put("requestid", requestId);
        // 设置开始时间和requestId，用于response时计算请求耗时和对应的requestId
        httpServletRequest.setAttribute(APIConstant.API_BEGIN_TIME, System.currentTimeMillis());
        httpServletRequest.setAttribute(APIConstant.API_GUID,requestId);

        // 由于 request.getInputStream()只能读1次，因此如果需要在congtroller前获取body参数做日志记录，只能重写HttpServletRequestWrapper包装类
        // Spring提供了类似的功能，比如ContentCachingRequestWrapper，但存在bug，必须在doFilter操作后进行。如不计较也可直接使用。
        CustomCachingRequestWrapper wrapperRequest = new CustomCachingRequestWrapper(httpServletRequest);
        // 请求参数日志
        LogUtils.logRequestParams(httpServletRequest,wrapperRequest);

        filterChain.doFilter(wrapperRequest, httpServletResponse);
    }

}
